/*
 * AESTools.cpp
 *
 *   Created on: 2010-3-27     
 *  Description: 
 *    Copyright: 2010 @ ICT Li Heyuan
 */

#include "../include/AESTools.h"
#include <stdexcept>
#include <sstream>
#include <iostream>
#include <ostream>
using std::cout;
using std::endl;
using std::runtime_error;

#include "../include/encode.h"
#include "../include/decode.h"
#include "../include/cencode.h"
#include "../include/cdecode.h"

AESTools::AESTools(const string &key)
{
	//检查key长度
	_key_len = key.size();
	if (_key_len != 16 && _key_len != 24 && _key_len != 32)
	{
		throw runtime_error("key size must be 16/24/32 bytes");
	}

	string::size_type i = 0;
	for (; i < key.size(); i++)
	{
		_key[i] = key[i];
	}

	/*	cout << _key_len << endl;*/
}

AESTools::AESTools()
{
	_key_len = 0;
}

AESTools& AESTools::operator =(const AESTools &right)
{
	memcpy(_key, right._key, sizeof(right._key));
	this->_key_len = right._key_len;

	return *this;
}

AESTools::~AESTools()
{

}

void AESTools::encrypt(const string&plain, string &cipher)
{
	//加密
	ECB_Mode<AES>::Encryption ecbEncryption(_key, _key_len);
	StringSource(plain, true, new StreamTransformationFilter(ecbEncryption,
			new StringSink(cipher)) // StreamTransformationFilter
	);
	return;
}

void AESTools::decrypt(const string &cipher, string &plain)
{
	//解密
	ECB_Mode<AES>::Decryption ecbDecryption(_key, _key_len);
	StringSource(cipher, true, new StreamTransformationFilter(ecbDecryption,
			new StringSink(plain)) // StreamTransformationFilter
	); // StringSource


	return;
}

string AESTools::getKey()
{
	return string((char *) _key, _key_len);
}

string AESTools::encryptWithBase64(const string &plain)
{
	//先加密
	string cipher;
	encrypt(plain, cipher);

	//转化成Base64编码
	std::istringstream in(cipher);
	std::ostringstream out;
	base64::encoder E;
	E.encode(in, out);

	return out.str();
}

string AESTools::decryptWithBase64(const string &cipher_b64)
{
	try
	{
		//先base64解码
		std::istringstream in(cipher_b64);
		std::ostringstream out;

		base64::decoder D;
		D.decode(in, out);
		string cipher = out.str();

		//解密
		string plain;
		decrypt(cipher, plain);

		return plain;
	} catch (runtime_error& err)
	{
		/*		cout << err.what();*/
		return string();
	}
}
